using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace ThinkJot.Core.Blogs.Providers.Xml
{
    [Serializable]
    public class BlogEntryTags
    {
        public class BlogEntryTagsItem
        {
            string tag;
            public string Tag
            {
                get { return tag; }
                set { tag = value; }
            }

            List<Guid> entryIds = new List<Guid>();
            public List<Guid> EntryIds
            {
                get { return entryIds; }
                set { entryIds = value; }
            }
        }

        private const string BlogEntryTagsFileName = "blogentrytags.xml";
        private List<BlogEntryTagsItem> tagEntryMap = new List<BlogEntryTagsItem>();
        public List<BlogEntryTagsItem> TagEntryMap
        {
            get { return tagEntryMap; }
            set { tagEntryMap = value; }
        }

        public List<Guid> GetEntryIdsForTag(string tag)
        {
            foreach (BlogEntryTagsItem item in TagEntryMap)
            {
                if (item.Tag == tag)
                    return item.EntryIds;
            }
            return new List<Guid>();
        }

        public void AddTagAndEntry(string tag, Guid entryId)
        {
            foreach (BlogEntryTagsItem item in tagEntryMap)
            {
                if (item.Tag == tag)
                {
                    item.EntryIds.Add(entryId);
                    return;
                }
            }
            BlogEntryTagsItem tagsItem = new BlogEntryTagsItem();
            tagsItem.Tag = tag;
            tagsItem.EntryIds.Add(entryId);
            tagEntryMap.Add(tagsItem);
        }

        public void RemoveEntry(Guid entryId)
        {
            List<BlogEntryTagsItem> fullItemRemovalList = new List<BlogEntryTagsItem>();
            foreach (BlogEntryTagsItem item in tagEntryMap)
            {
                item.EntryIds.Remove(entryId);
                //if the item does not contain any entryIds, remove the whole thing.
                if (item.EntryIds.Count == 0)
                    fullItemRemovalList.Add(item);
            }
            foreach (BlogEntryTagsItem item in fullItemRemovalList)
                tagEntryMap.Remove(item);
        }

        public static List<Guid> GetEntriesByTag(string tag, string blogName)
        {
            try
            {
                SerializationHelper serializer = new SerializationHelper();
                string tagMapPath = Path.Combine(ProviderSettings.GetBlogContentFolder(blogName), BlogEntryTagsFileName);
                BlogEntryTags tags = (BlogEntryTags)serializer.Deserialize(tagMapPath, typeof(BlogEntryTags), ProviderSettings.NamespaceURI);
                if (tags != null)
                {
                    return tags.GetEntryIdsForTag(tag);
                }
                return new List<Guid>();
            }
            catch (Exception ex)
            {
                new XmlLogger().LogException(ex, blogName);
                return new List<Guid>();
            }
        }

        public static void SetTagsToEntry(List<string> tags, Guid entryId, string blogName)
        {
            RemoveEntry(entryId, blogName);

            if (tags == null || tags.Count == 0)
                return;
            try
            {
                SerializationHelper serializer = new SerializationHelper();
                string tagMapPath = Path.Combine(ProviderSettings.GetBlogContentFolder(blogName), BlogEntryTagsFileName);
                BlogEntryTags blogEntryTags = (BlogEntryTags)serializer.Deserialize(tagMapPath, typeof(BlogEntryTags), ProviderSettings.NamespaceURI);
                if (blogEntryTags == null)
                    blogEntryTags = new BlogEntryTags();
                if (blogEntryTags != null)
                {
                    foreach (string tag in tags)
                    {
                        blogEntryTags.AddTagAndEntry(tag, entryId);
                    }
                }
                serializer.Serialize(blogEntryTags, tagMapPath, ProviderSettings.NamespaceURI);
            }
            catch(Exception ex)
            {
                new XmlLogger().LogException(ex, blogName);
            }
        }

        public static void RemoveEntry(Guid entryId, string blogName)
        {
            try
            {
                SerializationHelper serializer = new SerializationHelper();
                string tagMapPath = Path.Combine(ProviderSettings.GetBlogContentFolder(blogName), BlogEntryTagsFileName);
                BlogEntryTags blogEntryTags = (BlogEntryTags)serializer.Deserialize(tagMapPath, typeof(BlogEntryTags), ProviderSettings.NamespaceURI);
                if (blogEntryTags == null) return;
                blogEntryTags.RemoveEntry(entryId);
                serializer.Serialize(blogEntryTags, tagMapPath, ProviderSettings.NamespaceURI);
            }
            catch (Exception ex)
            {
                new XmlLogger().LogException(ex, blogName);
            }
        }
    }
}
